/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, Hardware
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <fcntl.h>
#include <fstream>
#include <ctime>

#include "gtest/gtest.h"
#include "hmfs_test_utils.h"

using namespace testing;
using namespace testing::ext;

namespace OHOS {
namespace Hmfs {
class ResizeHmfsMultiTest : public testing::Test {
public:
    static void SetUpTestCase();
    static void TearDownTestCase();
    void SetUp() override;
    void TearDown() override;
    static int32_t ExecResizeBinary(std::string tool, std::vector<std::string> &params, std::string device);
    static int32_t ExecutableCmd(const char *path, char *const argv[]);
    static int32_t ExecutableDdCmd(std::string& device, const int32_t count);
    static int32_t ExecutableRmCmd(std::string file);
    static int32_t ExecutableMkfsCmd(std::string tool, std::string& device);
    static int32_t ExecutableCmdWithOutput(std::vector<std::string>& params, std::string& outputFile);
    static int32_t ExecResizeBinaryWithOutput(std::string tool, std::vector<std::string>& params, 
        std::string device, std::string& outputFile);
    static int32_t ExecFsckWithOutput(std::string& device, std::string& outputFile);
    void PrintResizeParameters(const std::vector<std::string> &params);
    uint64_t GetDeviceSectorCount(const std::string& filePath);
};

void ResizeHmfsMultiTest::SetUpTestCase() {}

void ResizeHmfsMultiTest::TearDownTestCase() {}

void ResizeHmfsMultiTest::SetUp() {}

void ResizeHmfsMultiTest::TearDown()
{
    std::vector<char*> argv;
    argv.push_back(const_cast<char*>("/bin/sh"));
    argv.push_back(const_cast<char*>("-c"));
    argv.push_back(const_cast<char*>("rm -rf /data/Fs* /data/HM*")); 
    argv.push_back(nullptr);
    
    ResizeHmfsMultiTest::ExecutableCmd(argv[0], argv.data());
}

int32_t ResizeHmfsMultiTest::ExecutableRmCmd(std::string file)
{
    std::vector<char*> argv;
    argv.push_back(const_cast<char*>("/bin/sh"));
    argv.push_back(const_cast<char*>("-c"));
    argv.push_back(const_cast<char*>(("rm -rf " + file).c_str())); 
    argv.push_back(nullptr);
    
    return ResizeHmfsMultiTest::ExecutableCmd(argv[0], argv.data());
}

int32_t ResizeHmfsMultiTest::ExecutableCmd(const char *path, char *const argv[])
{
    if (path == nullptr || argv == nullptr ) {
        return -1;
    }

    pid_t pid = fork();
    if (pid < 0) {
        return -errno;
    }

    if (pid == 0) {
        execv(path, argv);
        _exit(EXIT_FAILURE);
    }

    int status = -1;
    pid_t wpid = waitpid(pid, &status, 0);
    if (wpid == -1 || wpid != pid) {
        return -errno;
    }

    if (WIFEXITED(status)) {
        return WEXITSTATUS(status);
    }
    return -ECHILD;
}

int32_t ResizeHmfsMultiTest::ExecutableCmdWithOutput(std::vector<std::string>& params, std::string& outputFile)
{
    pid_t pid = fork();
    if (pid < 0) {
        return -errno;
    }

    if (pid == 0) {
        int fd = open(outputFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
        if (fd < 0) {
            _exit(EXIT_FAILURE);
        }
        dup2(fd, STDOUT_FILENO);
        close(fd);

        std::vector<char*> argv;
        for (const auto& param : params) {
            argv.push_back(const_cast<char*>(param.c_str()));
        }
        argv.push_back(nullptr);
        execv(argv[0], argv.data());
        _exit(EXIT_FAILURE);
    }

    int status = -1;
    pid_t wpid = waitpid(pid, &status, 0);
    if (wpid == -1 || wpid != pid) {
        return -errno;
    }

    if (WIFEXITED(status)) {
        return WEXITSTATUS(status);
    }
    return -ECHILD;
}


int32_t ResizeHmfsMultiTest::ExecutableMkfsCmd(std::string tool, std::string& device)
{
    std::vector<char*> argv;
    argv.push_back(const_cast<char*>(("/system/bin/mkfs." + tool).c_str()));
    argv.push_back(const_cast<char*>((device).c_str()));
    argv.push_back(nullptr);
    return ResizeHmfsMultiTest::ExecutableCmd(argv[0], argv.data());
}

int32_t ResizeHmfsMultiTest::ExecutableDdCmd(std::string& device, int32_t count)
{
    std::string countStr = std::to_string(count);
    std::vector<char*> argv;
    argv.push_back(const_cast<char*>("/system/bin/dd"));
    argv.push_back(const_cast<char*>("if=/dev/zero"));
    argv.push_back(const_cast<char*>(("of=" + device).c_str()));
    argv.push_back(const_cast<char*>("bs=1M"));
    argv.push_back(const_cast<char*>(("count=" + countStr).c_str()));
    argv.push_back(nullptr);
    return ResizeHmfsMultiTest::ExecutableCmd(argv[0], argv.data());
}

int32_t ResizeHmfsMultiTest::ExecResizeBinary(std::string tool, std::vector<std::string> &params, std::string device)
{
    std::vector<char*> argv;
    argv.push_back(const_cast<char*>(("/system/bin/resize." + tool).c_str()));
    for (const auto &param : params) {
        argv.push_back(const_cast<char*>(param.c_str()));
    }
    argv.push_back(const_cast<char*>(device.c_str()));
    argv.push_back(nullptr);
    return ResizeHmfsMultiTest::ExecutableCmd(argv[0], argv.data());
}

int32_t ResizeHmfsMultiTest::ExecResizeBinaryWithOutput(std::string tool, std::vector<std::string>& params,
    std::string device, std::string& outputFile)
{
    std::vector<std::string> argv;
    argv.push_back("/system/bin/resize." + tool);
    for (const auto& param : params) {
        argv.push_back(param);
    }
    argv.push_back(device);
    return ExecutableCmdWithOutput(argv, outputFile);
}

int32_t ResizeHmfsMultiTest::ExecFsckWithOutput(std::string& device, std::string& outputFile)
{
    std::vector<std::string> argv;
    argv.push_back("/system/bin/fsck.f2fs");
    argv.push_back(device);
    return ExecutableCmdWithOutput(argv, outputFile);
}

void ResizeHmfsMultiTest::PrintResizeParameters(const std::vector<std::string> &params)
{
    std::cout << "+----------------------------------------------------------------+" << std::endl;
    for (int32_t i = 0; i < params.size(); i++) {
        std::cout << params[i] << " ";
    }
    std::cout << std::endl;
    std::cout << "+----------------------------------------------------------------+" << std::endl;
}

uint64_t ResizeHmfsMultiTest::GetDeviceSectorCount(const std::string& filePath)
{
    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
    GetSuperBlock(filePath, hmfsSuperBlock);

    return hmfsSuperBlock->blockCount * DEFAULT_SECTORS_PER_BLOCK;
}

/*
 * @tc.name: ResizeHmfsMultiTest_MultiParams_001
 * @tc.desc: Test resize.hmfs with multiple random parameters.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_MultiParams_001, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_MultiParams_001 BEGIN" << std::endl;
    std::string device = "/data/FsMultiTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(device, 1000));
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("f2fs", device));

    std::vector<std::string> params;
    params.clear();
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("1024000");
    params.push_back("-O");
    params.push_back("extra_attr,project_quota,casefold");
    params.push_back("-C");
    params.push_back("utf8");
    params.push_back("-i");
    params.push_back("-o");
    params.push_back("60");
    params.push_back("-d");
    params.push_back("1");
    std::string outputFile = "/data/test_output.txt";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecResizeBinaryWithOutput("f2fs", params, device, outputFile));
    std::string output = ReadFile(outputFile);
    EXPECT_TRUE(output.find("Info: Done to update superblock") != std::string::npos);
    EXPECT_TRUE(output.find("Info: Debug level = 1") != std::string::npos);

    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
    GetSuperBlock(device, f2fsSuperBlock);
    auto f2fsCheckPoint = std::make_unique<CheckPointData>();
    GetCheckPoint(device, f2fsCheckPoint);

    std::string hmDevice = "/data/HMFsTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(hmDevice, 100));
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("hmfs", hmDevice));
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecResizeBinary("hmfs", params, hmDevice));

    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
    GetSuperBlock(hmDevice, hmfsSuperBlock);
    auto hmfsCheckPoint = std::make_unique<CheckPointData>();
    GetCheckPoint(hmDevice, hmfsCheckPoint);
    ASSERT_EQ(f2fsCheckPoint->cpFlags, hmfsCheckPoint->cpFlags);
    ASSERT_EQ(f2fsCheckPoint->checksumOffset, hmfsCheckPoint->checksumOffset);
    ASSERT_EQ(f2fsCheckPoint->overprovSegmentCount, hmfsCheckPoint->overprovSegmentCount);
    ASSERT_EQ(f2fsCheckPoint->rsvdSegmentCount, hmfsCheckPoint->rsvdSegmentCount);
    ASSERT_EQ(f2fsSuperBlock->encoding, hmfsSuperBlock->encoding);
    ASSERT_EQ(f2fsSuperBlock->encodingFlags, hmfsSuperBlock->encodingFlags);
    ASSERT_EQ(f2fsSuperBlock->features, hmfsSuperBlock->features);
    ASSERT_EQ(f2fsSuperBlock->blockCount, hmfsSuperBlock->blockCount);

    ASSERT_EQ(hmfsSuperBlock->encoding, HMFS_ENC_UTF8_12_1);
    ASSERT_TRUE(hmfsSuperBlock->features & HMFS_FEATURE_CASEFOLD);
    ASSERT_TRUE(hmfsSuperBlock->features & HMFS_FEATURE_PRJQUOTA);
    ASSERT_TRUE(hmfsSuperBlock->features & HMFS_FEATURE_EXTRA_ATTR);
    ASSERT_TRUE(hmfsCheckPoint->cpFlags & CP_FLAG_LARGE_NAT_BITMAP);

    std::string HmfsFsckOutFileName = "/data/Fsck_Hmfs_MultiParams_001.txt";
    std::string F2fsFsckOutFileName = "/data/Fsck_F2fs_MultiParams_001.txt";
    int32_t fsckF2fsRes = ResizeHmfsMultiTest::ExecFsckWithOutput(hmDevice, HmfsFsckOutFileName);
    int32_t fsckHmfsRes = ResizeHmfsMultiTest::ExecFsckWithOutput(device, F2fsFsckOutFileName);
    ASSERT_EQ(fsckF2fsRes, fsckHmfsRes);
    ASSERT_TRUE(PrintFsckErrorMsg(HmfsFsckOutFileName, hmDevice));
    if (fsckF2fsRes == fsckHmfsRes && fsckHmfsRes == 0) {
        if (PrintFsckErrorMsg(F2fsFsckOutFileName, device)) {
            ASSERT_EQ(0, ExecutableRmCmd(HmfsFsckOutFileName));
            ASSERT_EQ(0, ExecutableRmCmd(F2fsFsckOutFileName));
        }
    }

    std::cout << "-------------------------------------------------------------------------F2FS" << std::endl;
    PrintSuperBlockAndCheckPointData(device);
    std::cout << "-------------------------------------------------------------------------HMFS" << std::endl;
    PrintSuperBlockAndCheckPointData(hmDevice);

    std::cout << "ResizeHmfsMultiTest_MultiParams_001 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_MultiParams_002
 * @tc.desc: Test resize.hmfs with multiple random parameters.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_MultiParams_002, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_MultiParams_002 BEGIN" << std::endl;
    std::srand(std::time(nullptr)); // 初始化随机数种子
    std::string device = "/data/FsMultiTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(device, 1000));

    std::string hmDevice = "/data/HMFsTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(hmDevice, 1000));

    for (int i = 0; i < 2000; ++i) {
        ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("f2fs", device));
        ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("hmfs", hmDevice));
        uint64_t sectorCount = ResizeHmfsMultiTest::GetDeviceSectorCount(hmDevice);

        std::vector<std::string> generateParams = GenerateParams();
        ResizeHmfsMultiTest::PrintResizeParameters(generateParams);

        std::map<std::string, std::string> parameterMap{};
        int32_t verifParameters = CheckResizeParameters(hmDevice, generateParams, sectorCount, parameterMap);

        std::string hmfsOutputFile = "/data/test_output_hmfs_multi_" + std::to_string(i) + ".txt";
        std::string f2fsOutputFile = "/data/test_output_f2fs_multi_" + std::to_string(i) + ".txt";
        int32_t f2fsResult = ResizeHmfsMultiTest::ExecResizeBinaryWithOutput("f2fs", generateParams, device, f2fsOutputFile);
        int32_t hmfsResult = ResizeHmfsMultiTest::ExecResizeBinaryWithOutput("hmfs", generateParams, hmDevice, hmfsOutputFile);
        std::string output = ReadFile(hmfsOutputFile);

        auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
        GetSuperBlock(device, f2fsSuperBlock);
        auto f2fsCheckPoint = std::make_unique<CheckPointData>();
        GetCheckPoint(device, f2fsCheckPoint);

        auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
        GetSuperBlock(hmDevice, hmfsSuperBlock);
        auto hmfsCheckPoint = std::make_unique<CheckPointData>();
        GetCheckPoint(hmDevice, hmfsCheckPoint);
        PrintSuperBlockAndCheckPointData(hmDevice);
        
        if (verifParameters == NEED_SAFE_RESIZE_FLAG) {
            ASSERT_TRUE(output.find("Nothing to resize, now only supports resizing with safe resize flag") != std::string::npos);
            ASSERT_EQ(0, ExecutableRmCmd(hmfsOutputFile));
            ASSERT_EQ(0, ExecutableRmCmd(f2fsOutputFile));
        } else if (verifParameters == OUT_OF_RANGE) {
            ASSERT_TRUE(output.find("Out-of-range Target") != std::string::npos);
            ASSERT_EQ(0, ExecutableRmCmd(hmfsOutputFile));
            ASSERT_EQ(0, ExecutableRmCmd(f2fsOutputFile));
        } else if (verifParameters == MORE_SEGMENT_NEEDED) {
            ASSERT_TRUE(output.find("Error: Device size is not sufficient for F2FS volume, more segment needed") != std::string::npos);
            ASSERT_EQ(0, ExecutableRmCmd(hmfsOutputFile));
            ASSERT_EQ(0, ExecutableRmCmd(f2fsOutputFile));
        } else if (verifParameters == VALID) {
            ASSERT_EQ(f2fsResult, hmfsResult);
            if (hmfsResult == 0) {
                ASSERT_TRUE(!output.empty());
                // 对比hmfs和f2fs字段一致
                SuperBlockCode compSB = CompareSuperBlock(f2fsSuperBlock, hmfsSuperBlock);
                ASSERT_EQ(SUCCESSED_SB, compSB);
                CheckPointCode compCP = ERROR_CP_UNKNOWN;
                if (f2fsCheckPoint != nullptr && hmfsCheckPoint != nullptr) {
                    compCP = CompareCheckPoint(f2fsCheckPoint, hmfsCheckPoint);
                    ASSERT_EQ(SUCCESSED_CP, compCP);
                }
                if (output.find("Info: Done to update superblock") != std::string::npos &&
                    output.find("Info: Done to rebuild checkpoint blocks") != std::string::npos) {
                    ASSERT_TRUE(CheckResizeHmfsResult(parameterMap, hmfsCheckPoint, hmfsSuperBlock, output));
                    if (CheckResizeHmfsResult(parameterMap, hmfsCheckPoint, hmfsSuperBlock, output))
                    {
                        ASSERT_EQ(0, ExecutableRmCmd(hmfsOutputFile));
                        ASSERT_EQ(0, ExecutableRmCmd(f2fsOutputFile));
                    }
                } else {
                    SuperBlockCode compSB = CompareSuperBlock(f2fsSuperBlock, hmfsSuperBlock);
                    ASSERT_EQ(SUCCESSED_SB, compSB);
                    CheckPointCode compCP = ERROR_CP_UNKNOWN;
                    if (f2fsCheckPoint != nullptr && hmfsCheckPoint != nullptr) {
                        compCP = CompareCheckPoint(f2fsCheckPoint, hmfsCheckPoint);
                        ASSERT_EQ(SUCCESSED_CP, compCP);
                    }
                    // ASSERT_EQ(0, ExecutableRmCmd(hmfsOutputFile));
                    // ASSERT_EQ(0, ExecutableRmCmd(f2fsOutputFile));
                }
            }
            std::string HmfsFsckOutFileName = "/data/Fsck_Hmfs_MultiParams_002_" + std::to_string(i) + ".txt";;
            std::string F2fsFsckOutFileName = "/data/Fsck_F2fs_MultiParams_002_" + std::to_string(i) + ".txt";
            int32_t fsckHmfsRes = ResizeHmfsMultiTest::ExecFsckWithOutput(hmDevice, HmfsFsckOutFileName);
            int32_t fsckF2fsRes = ResizeHmfsMultiTest::ExecFsckWithOutput(device, F2fsFsckOutFileName);
            ASSERT_EQ(fsckF2fsRes, fsckHmfsRes);
            ASSERT_TRUE(PrintFsckErrorMsg(HmfsFsckOutFileName, hmDevice));
            if (fsckF2fsRes == fsckHmfsRes && fsckHmfsRes == 0) {
                if (PrintFsckErrorMsg(F2fsFsckOutFileName, device)) {
                    ASSERT_EQ(0, ExecutableRmCmd(HmfsFsckOutFileName));
                    ASSERT_EQ(0, ExecutableRmCmd(F2fsFsckOutFileName));
                }
            }
        }
    }
    std::cout << "ResizeHmfsMultiTest_MultiParams_002 END" << std::endl;
}

#ifdef AAA
/*
 * @tc.name: ResizeHmfsMultiTest_MultiParams_003
 * @tc.desc: Test resize.hmfs multiple times with randomly generated parameters.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_MultiParams_003, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_MultiParams_003 BEGIN" << std::endl;
    std::srand(std::time(nullptr));
    std::string device = "/data/FsMultiTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(device, 100));
    std::string hmDevice = "/data/HMFsTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(hmDevice, 100));

    for (int32_t i = 0; i < 10; ++i) {
        std::cout << "---- Iteration " << i + 1 << " ----" << std::endl;
        ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("f2fs", device));
        ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("f2fs", hmDevice));
        uint64_t sectorCount = ResizeHmfsMultiTest::GetDeviceSectorCount(hmDevice);
        for (int j = 0; j < 5; ++j) {
            std::cout << "Resize attempt " << j + 1 << " for iteration " << i + 1 << std::endl;
            std::vector<std::string> generateParams = GenerateParams(); 
            ResizeHmfsMultiTest::PrintResizeParameters(generateParams);
            std::map<std::string, std::string> parameterMap{};
            int32_t verifParameters = CheckResizeParameters(hmDevice, generateParams, sectorCount, parameterMap);

            std::string outputFile = "/data/test_output_multi_" + std::to_string(i) + "_" + std::to_string(j) + ".txt";
            int32_t f2fsResult = ResizeHmfsMultiTest::ExecResizeBinary("f2fs", generateParams, device);
            int32_t hmfsResult = ResizeHmfsMultiTest::ExecResizeBinaryWithOutput("f2fs", generateParams, hmDevice, outputFile);
            std::string output = ReadFile(outputFile);

            std::string HmfsFsckOutFileName = "/data/Mkfs_Hmfs_Fsck_MultiParams_002_" + std::to_string(i) + ".txt";;
            std::string F2fsFsckOutFileName = "/data/Mkfs_F2fs_Fsck_MultiParams_002_" + std::to_string(i) + ".txt";
            int32_t fsckF2fsRes = ResizeHmfsMultiTest::ExecFsckWithOutput(hmfsDevice, HmfsFsckOutFileName);
            int32_t fsckHmfsRes = ResizeHmfsMultiTest::ExecFsckWithOutput(device, F2fsFsckOutFileName);
            ASSERT_EQ(fsckF2fsRes, fsckHmfsRes);
            if (fsckF2fsRes == fsckHmfsRes && fsckHmfsRes == 0) {
                if (PrintFsckErrorMsg(F2fsFsckOutFileName, device)) {
                    ASSERT_TRUE(PrintFsckErrorMsg(HmfsFsckOutFileName, hmDevice));
                }
            }

            if (verifParameters == NEED_SAFE_RESIZE_FLAG) {
                ASSERT_TRUE(output.find("Nothing to resize, now only supports resizing with safe resize flag") != std::string::npos);
                ASSERT_EQ(0, ExecutableRmCmd(outputFile));
            } else if (verifParameters == OUT_OF_RANGE) {
                ASSERT_TRUE(output.find("Out-of-range Target") != std::string::npos);
                ASSERT_EQ(0, ExecutableRmCmd(outputFile));
            } else if (verifParameters == MORE_SEGMENT_NEEDED) {
                ASSERT_TRUE(output.find("Error: Device size is not sufficient for F2FS volume, more segment needed") != std::string::npos);
                ASSERT_EQ(0, ExecutableRmCmd(outputFile));
            } else if (verifParameters == VALID) {
                ASSERT_EQ(f2fsResult, hmfsResult);
                if (hmfsResult == 0) {
                    ASSERT_TRUE(!output.empty());
                    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
                    GetSuperBlock(device, f2fsSuperBlock);
                    auto f2fsCheckPoint = std::make_unique<CheckPointData>();
                    GetCheckPoint(device, f2fsCheckPoint);
                    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
                    GetSuperBlock(hmDevice, hmfsSuperBlock);
                    auto hmfsCheckPoint = std::make_unique<CheckPointData>();
                    GetCheckPoint(hmDevice, hmfsCheckPoint);
                    // PrintSuperBlockAndCheckPointData(hmDevice);

                    SuperBlockCode compSB = CompareSuperBlock(f2fsSuperBlock, hmfsSuperBlock);
                    ASSERT_EQ(SUCCESSED_SB, compSB);
                    CheckPointCode compCP = ERROR_CP_UNKNOWN;
                    if (f2fsCheckPoint != nullptr && hmfsCheckPoint != nullptr) {
                        compCP = CompareCheckPoint(f2fsCheckPoint, hmfsCheckPoint);
                        ASSERT_EQ(SUCCESSED_CP, compCP);
                    }
                    if (output.find("Info: Done to update superblock") != std::string::npos &&
                        output.find("Info: Done to rebuild checkpoint blocks") != std::string::npos) {
                        ASSERT_TRUE(CheckResizeHmfsResult(parameterMap, hmfsCheckPoint, hmfsSuperBlock, output));
                        if (CheckResizeHmfsResult(parameterMap, hmfsCheckPoint, hmfsSuperBlock, output))
                        {
                            ASSERT_EQ(0, ExecutableRmCmd(outputFile));
                        }
                    }
                }
            }
        }
    }
    std::cout << "ResizeHmfsMultiTest_MultiParams_003 END" << std::endl;
}
#endif

/*
 * @tc.name: ResizeHmfsMultiTest_ExitUnexpectedly_001
 * @tc.desc: Test resize.hmfs multiple times with randomly generated parameters.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_ExitUnexpectedly_001, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_ExitUnexpectedly_001 BEGIN" << std::endl;
    std::string device = "/data/FsTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(device, 1000));
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("f2fs", device));
    std::vector<std::string> params;
    params.clear();
    params.push_back("-O");
    params.push_back("extra_attr,project_quota");
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("102400");
    std::string outputFile = "/data/test_output.txt";
    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
    pid_t pid = fork();
    if (pid < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pid == 0) {
        ASSERT_EQ(0, ResizeHmfsMultiTest::ExecResizeBinary("f2fs", params, device));
        sleep(10);
    }
    while (true) {
        GetSuperBlock(device, f2fsSuperBlock);
        uint32_t features = f2fsSuperBlock->features;
        if (features & HMFS_FEATURE_EXTRA_ATTR) {
            kill(pid, SIGKILL);
            break;
        }
    }
    params.clear();
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("102400");
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecResizeBinaryWithOutput("f2fs", params, device, outputFile));
    std::cout << "ResizeHmfsMultiTest_ExitUnexpectedly_001 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_ExitUnexpectedly_002
 * @tc.desc: Test resize.hmfs multiple times with randomly generated parameters.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_ExitUnexpectedly_002, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_ExitUnexpectedly_002 BEGIN" << std::endl;
    std::string hmDevice = "/data/HMFsTest";
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableDdCmd(hmDevice, 1000));
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecutableMkfsCmd("hmfs", hmDevice));
    std::vector<std::string> params;
    params.clear();
    params.push_back("-O");
    params.push_back("extra_attr,project_quota");
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("102400");
    std::string outputFile = "/data/test_output.txt";
    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
    pid_t pid = fork();
    if (pid < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pid == 0) {
        ASSERT_EQ(0, ResizeHmfsMultiTest::ExecResizeBinary("hmfs", params, hmDevice));
        sleep(10);
    }
    while (true) {
        GetSuperBlock(hmDevice, hmfsSuperBlock);
        uint32_t features = hmfsSuperBlock->features;
        if (features & HMFS_FEATURE_EXTRA_ATTR) {
            kill(pid, SIGKILL);
            break;
        }
    }
    params.clear();
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("102400");
    ASSERT_EQ(0, ResizeHmfsMultiTest::ExecResizeBinaryWithOutput("hmfs", params, hmDevice, outputFile));
    std::cout << "ResizeHmfsMultiTest_ExitUnexpectedly_002 END" << std::endl;
}
} // namespace Hmfs
} // namespace OHOS